package com.srmt.common.ratelimit;

import com.srmt.common.config.ApplicationConfig;
import com.srmt.common.ratelimit.config.RateLimitConfig;
import com.srmt.common.ratelimit.impl.LocalRateLimiter;
import com.srmt.common.ratelimit.impl.GuavaRateLimiter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

/**
 * 限流器工厂
 * 负责创建限流器实例，支持多种实现
 * 
 * @author SRMT Development Team
 * @since 1.0.0
 */
public class RateLimiterFactory {
    
    private static final Logger logger = LoggerFactory.getLogger(RateLimiterFactory.class);
    
    /**
     * 限流器类型枚举
     */
    public enum LimiterType {
        LOCAL("local"),                 // 本地令牌桶实现
        GUAVA("guava");                 // Google Guava实现（高精度本地）
        
        private final String value;
        
        LimiterType(String value) {
            this.value = value;
        }
        
        public String getValue() {
            return value;
        }
        
        public static LimiterType fromString(String value) {
            if (value == null) {
                return LOCAL;
            }
            for (LimiterType type : values()) {
                if (type.value.equalsIgnoreCase(value)) {
                    return type;
                }
            }
            logger.warn("未知的限流器类型: {}, 使用LOCAL作为默认值", value);
            return LOCAL;
        }
    }
    
    /**
     * 从ApplicationConfig创建限流器
     *
     * @param applicationConfig 应用配置
     * @return 限流器实例
     * @throws IllegalArgumentException 如果配置为null
     * @throws IllegalStateException 如果限流未启用
     */
    public static RateLimiter createFromApplicationConfig(ApplicationConfig applicationConfig) {
        if (applicationConfig == null) {
            throw new IllegalArgumentException("应用配置对象不能为null");
        }

        if (!applicationConfig.getRateLimit().isEnabled()) {
            throw new IllegalStateException("速率限制ing is not enabled in configuration. " +
                "Use RateLimiterFactory.create() to create rate limiter manually, " +
                "or check caller logic to avoid calling this method when rate limiting is disabled.");
        }

        // 直接使用RateLimitConfig
        RateLimitConfig config = applicationConfig.getRateLimit();

        // 优先使用自定义限流器（用于分布式限流场景）
        RateLimiter customLimiter = config.getCustomRateLimiter();
        if (customLimiter != null) {
            logger.info("使用自定义限流器实现: {}", customLimiter.getClass().getSimpleName());
            return customLimiter;
        }

        // 根据类型创建限流器
        String limiterType = config.getProperty("limiter.type");
        if (limiterType == null) {
            limiterType = "local";  // 默认使用本地限流器
        }
        LimiterType type = LimiterType.fromString(limiterType);
        return create(type, config);
    }
    
    /**
     * 根据类型创建限流器
     * 
     * @param type 限流器类型
     * @param config 限流配置
     * @return 限流器实例
     */
    public static RateLimiter create(LimiterType type, RateLimitConfig config) {
        if (config == null) {
            throw new IllegalArgumentException("限流配置对象不能为null");
        }
        
        switch (type) {
            case GUAVA:
                logger.info("创建Guava限流器(高精度本地)");
                return new GuavaRateLimiter(config);
            
            case LOCAL:
            default:
                logger.info("创建本地限流器");
                return new LocalRateLimiter(config);
        }
    }
    
    /**
     * 根据配置自动选择限流器类型
     * 
     * @param config 限流配置
     * @return 限流器实例
     */
    public static RateLimiter createAuto(RateLimitConfig config) {
        // 从配置中读取限流器类型
        String typeStr = config.getProperty("limiter.type");
        LimiterType type = LimiterType.fromString(typeStr);
        
        logger.info("自动创建限流器,类型: {}", type);
        return create(type, config);
    }
    
    
    /**
     * 创建限流器
     * 允许用户传入自定义实现，如果为null则使用默认本地实现
     * 
     * @param customLimiter 用户自定义的限流器实现（可选）
     * @param config 限流配置
     * @return 限流器实例
     */
    public static RateLimiter create(RateLimiter customLimiter, RateLimitConfig config) {
        if (customLimiter != null) {
            logger.info("使用自定义限流器实现: {}", 
                       customLimiter.getClass().getSimpleName());
            return customLimiter;
        }
        
        // 如果没有自定义实现，则自动选择
        return createAuto(config);
    }
}